package com.stone.design.mode.pipeline.netty.pipeline;

import com.stone.design.mode.pipeline.netty.context.AbstractChannelHandlerContext;
import com.stone.design.mode.pipeline.netty.context.ChannelHandlerContext;
import com.stone.design.mode.pipeline.netty.context.DefaultChannelHandlerContext;
import com.stone.design.mode.pipeline.netty.handler.ChannelHandler;
import com.stone.design.mode.pipeline.netty.handler.in.ChannelInboundHandler;
import com.stone.design.mode.pipeline.netty.handler.out.ChannelOutboundHandler;
import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.Executor;

/**
 * 默认的pipeline实现
 * pipeline可以发起传播入站和出站事件
 *
 * @author wenpan 2024/01/21 17:20
 */
@Slf4j
public class DefaultChannelPipeline implements ChannelPipeline {

    private static final String HEAD_NAME = generateName0(HeadContext.class);
    private static final String TAIL_NAME = generateName0(TailContext.class);

    /**
     * pipeline中的头结点
     */
    final AbstractChannelHandlerContext head;
    /**
     * pipeline中的尾结点
     */
    final AbstractChannelHandlerContext tail;

    public DefaultChannelPipeline() {
        // 该pipeline上的handler头节点
        tail = new TailContext(this);
        // 该pipeline上的handler尾节点
        head = new HeadContext(this);

        head.next = tail;
        tail.prev = head;
    }

    @Override
    public ChannelPipeline addLast(String name, Executor executor, ChannelHandler handler) {
        synchronized (this) {
            //检查同一个channelHandler实例是否允许被重复添加
//            checkMultiplicity(handler);

            AbstractChannelHandlerContext newCtx = newContext(executor, name, handler);
            // 添加
            addLast0(newCtx);
        }
        return this;
    }

    @Override
    public ChannelPipeline addLast(String name, ChannelHandler handler) {
        return addLast(name, null, handler);
    }

    /**
     * pipeline上发布出站事件，从尾节点开始向前传播
     */
    @Override
    public ChannelPipeline flush() {
        // 从尾节点向前传播flush事件，直接调用tail节点的方法
        tail.flush();
        return this;
    }

    /**
     * pipeline上发布入站事件，从头节点开始向后传播
     */
    @Override
    public ChannelInboundInvoker fireChannelRegistered() {
        // 从头节点开始向后传播入站事件
        AbstractChannelHandlerContext.invokeChannelRegistered(head);
        return this;
    }

    /**
     * pipeline上发布入站事件，从头节点开始向后传播
     */
    @Override
    public ChannelInboundInvoker fireChannelActive() {
        // 从头节点开始向后传播入站事件
        AbstractChannelHandlerContext.invokeChannelActive(head);
        return this;
    }

    private static String generateName0(Class<?> handlerType) {
        return handlerType.getSimpleName() + "#0";
    }

    /**
     * 创建一个context
     */
    private AbstractChannelHandlerContext newContext(Executor executor, String name, ChannelHandler handler) {
        return new DefaultChannelHandlerContext(this, executor, name, handler);
    }

    /**
     * 标准的双向链表尾插法
     */
    private void addLast0(AbstractChannelHandlerContext newCtx) {
        AbstractChannelHandlerContext prev = tail.prev;
        newCtx.prev = prev;
        newCtx.next = tail;
        prev.next = newCtx;
        tail.prev = newCtx;
    }

    /**
     * headContext即是一个入站处理器又是一个出站处理器又是一个context
     */
    final class HeadContext extends AbstractChannelHandlerContext implements ChannelOutboundHandler, ChannelInboundHandler {

        HeadContext(DefaultChannelPipeline pipeline) {
            super(HEAD_NAME, pipeline, null, HeadContext.class);
        }

        @Override
        public ChannelHandler handler() {
            // HeadContext 本身就是一个handler
            return this;
        }

        //
        // 入站处理器的能力
        // ------------------------------------------------------------------------

        @Override
        public void channelRegistered(ChannelHandlerContext ctx) throws Exception {
            // todo 这里做自己的逻辑
            log.info("HeadContext 接收到 channelRegistered 事件");
            // 继续向后传播
            ctx.fireChannelRegistered();
        }

        @Override
        public void channelActive(ChannelHandlerContext ctx) throws Exception {
            // todo 这里做自己的逻辑
            log.info("HeadContext 接收到 channelActive 事件");
            // 继续向后传播
            ctx.fireChannelActive();
        }

        //
        // 出站处理器的能力
        // ------------------------------------------------------------------------

        @Override
        public void flush(ChannelHandlerContext ctx) throws Exception {
            // 固定的xx操作，由于flush是出站操作，所以不用再继续传播了
            log.info("HeadContext 数据flush啦");
        }
    }

    /**
     * tailContext是一个入站处理器又是一个context
     */
    final class TailContext extends AbstractChannelHandlerContext implements ChannelInboundHandler {

        TailContext(DefaultChannelPipeline pipeline) {
            super(TAIL_NAME, pipeline, null, TailContext.class);
        }

        @Override
        public ChannelHandler handler() {
            // TailContext 本身就是一个handler
            return this;
        }

        //
        // 入站处理器的能力
        // ------------------------------------------------------------------------

        @Override
        public void channelRegistered(ChannelHandlerContext ctx) throws Exception {
            // 入站操作的最后节点，这里只打印日志兜底即可
            log.info("tailContext 接收到 channelRegistered");
        }

        @Override
        public void channelActive(ChannelHandlerContext ctx) throws Exception {
            // 入站操作的最后节点，这里只打印日志兜底即可
            log.info("tailContext 接收到 channelActive");
        }
    }
}
